package n6_monitor对象头_偏向锁;

import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;

import java.util.Vector;
import java.util.concurrent.locks.LockSupport;


/**
 <b>批量撤销</b>
 当撤销偏向锁阈值超过 40 次后，<i>jvm 会这样觉得，自己确实偏向错了，根本就不该偏向</i>。
 于是整个类的所有对象  都会变为不可偏向的，新建的对象也是不可偏向的

课程：https://www.bilibili.com/video/BV16J411h7Rd?p=86&spm_id_from=pageDriver

 偏向锁是默认是延迟的，不会在程序启动时立即生效，如果想避免延迟，可以加 [-- VM 参数  -XX:BiasedLockingStartupDelay=0 --]
 */
@Slf4j(topic = "c.T4")
public class T4_偏向锁_批量撤销 {



    static Thread t1,t2,t3;
    public static void main(String[] args) throws InterruptedException {
        Vector<Dog4> list = new Vector<>();

        // 1. 39 个对象加 偏向锁 ， 【偏向 t1 线程】
        int loopNumber = 39;
        t1 = new Thread(() -> {
            for (int i = 0; i < loopNumber; i++) {
                Dog4 d = new Dog4();
                list.add(d);
                synchronized (d) {
                    log.debug("<<<<<<-线程t1-<<<<<<----- "+i + " ----->>>>>>>-线程t1->>>>>" + "\t" + ClassLayout.parseInstance(d).toPrintable());
                }
            }
            // 2. 唤醒 t2 线程
            LockSupport.unpark(t2);
        }, "--- t1 ---");

        t1.start();

        // 3. 遍历 循环， 加锁    【前19个 偏向 t1,   后面偏向 t2】
        t2 = new Thread(() -> {
            LockSupport.park();
            log.debug("==================================线程 t2 开始======================================> ");
            for (int i = 0; i < loopNumber; i++) {
                Dog4 d = list.get(i);
                log.debug("【【【【【【【>>>>>>>>>>----- "+i + " -----<<<<<<<<<<<<<<<<<<<<" + "\t" + ClassLayout.parseInstance(d).toPrintable());
                // i < 19 时 ，升级为 【-轻量级锁-】             [ 达到 阈值后，偏向锁成 101 【偏向 t2 线程】 ]
                synchronized (d) {
                    log.debug("       <<<synchronized----- "+ i + " -----synchronized>>>     " + "\t" + ClassLayout.parseInstance(d).toPrintable());
                }
                // i < 19 时 ,解锁以后： 撤销成 001 不可偏向      [ 达到 阈值后，偏向锁成 101 【偏向 t2 线程】]
                log.debug(">>>>>>>>>>>>>>>>>>>>>>----- "+i + " -----<<<<<<<<<<<】】】】】】" + "\t" + ClassLayout.parseInstance(d).toPrintable());
            }

            // 4. 唤醒 t3 线程
            LockSupport.unpark(t3);
        }, "--- t2 ---");

        t2.start();

        /*
         5. 遍历循环， 加锁  [注意下面 1️⃣ 2️⃣ 3️⃣ 三个位置]
         ==============================================
         |  >>> 前19个 没偏向，是t2撤销成 轻量级锁来的     |
         |          1️⃣ 不可偏向状态 01                 |
         |          2️⃣ 同一个锁对象 升级轻量级锁 00      |
         |          3️⃣ 撤销 不可偏向状态 01             |
         ----------------------------------------------
         |  >>> 后面19个 是偏向t2的                     |
         |          1️⃣ 偏向 t2线程                     |
         |          2️⃣ 同一个锁对象 升级轻量级锁 00      |
         |          3️⃣ 撤销 不可偏向状态 01             |
         ==============================================
         */
        t3 = new Thread(() -> {
            LockSupport.park();
            log.debug("==================================线程 t3 开始======================================> ");
            for (int i = 0; i < loopNumber; i++) {
                Dog4 d = list.get(i);
                // 1️⃣
                log.debug("【【【【【【【>>>>>>>>>>----- "+i + " -----<<<<<<<<<<<<<<<<<<<<" + "\t" + ClassLayout.parseInstance(d).toPrintable());
                synchronized (d) {
                    // 2️⃣
                    log.debug("       <<<synchronized----- "+ i + " -----synchronized>>>     " + "\t" + ClassLayout.parseInstance(d).toPrintable());
                }
                // 3️⃣
                log.debug(">>>>>>>>>>>>>>>>>>>>>>----- "+i + " -----<<<<<<<<<<<】】】】】】" + "\t" + ClassLayout.parseInstance(d).toPrintable());
            }
        }, "--- t3 ---");
        t3.start();
        t3.join();

        /*
        6. 当撤销偏向锁阈值超过 40 次后, 再创建对象锁   整个类 都不会再偏向
        ===========================================
        |                                         |
        |   如果改成 38 会发现，最后这个打印 将是 101  |
        |                                         |
        |==========================================
         */
        log.debug(ClassLayout.parseInstance(new Dog4()).toPrintable());
    }





}
class Dog4 {}








